主要是懸浮視窗的幾個按鈕,我想做成平常能自動收起,觸碰畫面時再展開的效果。
將幾個按鈕放到LinearLayout中
<LinearLayout
android:id="@+id/toolsLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/one_grid_unit"
android:layout_marginTop="@dimen/one_grid_unit"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- ... -->
</LinearLayout>
private val collapseAnimatorSet = AnimatorSet()
private val collapseToolsRunnable = Runnable {
val toolsAnimator = ObjectAnimator.ofFloat(
binding.toolsLayout,
"translationY",
0f,
-100f.dpToPx(applicationContext).toFloat()
)
val closeAnimator = ObjectAnimator.ofFloat(
binding.close,
"translationX",
0f,
100f.dpToPx(applicationContext).toFloat()
)
collapseAnimatorSet.duration = 300L
collapseAnimatorSet.interpolator = AccelerateInterpolator()
collapseAnimatorSet.playTogether(toolsAnimator, closeAnimator)
collapseAnimatorSet.start()
}
private val collapseToolsInterval = 3000L
override fun onCreate() {
// ...
handler.postDelayed(collapseToolsRunnable, collapseToolsInterval)
// ...
}
展開的時機點是在觸碰RecyclerView時,首先先在Day22中客製的ControllableRecyclerView中加入Callback,並在dispatchTouchEvent中呼叫:
class ControllableRecyclerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
var touchable = true
var touchCallback: ((MotionEvent) -> Unit)? = null
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
touchCallback?.invoke(ev)
return (touchable && super.dispatchTouchEvent(ev))
}
}
在ObserverService中撰寫Callback:
private var isExpanding = false
override fun onCreate() {
// ...
binding.recyclerView.touchCallback = { event ->
collapseAnimatorSet.cancel()
handler.removeCallbacks(collapseToolsRunnable)
if (event.actionMasked == MotionEvent.ACTION_UP
|| event.actionMasked == MotionEvent.ACTION_CANCEL
) {
handler.postDelayed(collapseToolsRunnable, collapseToolsInterval)
} else {
if (binding.toolsLayout.translationY != 0f && !isExpanding) {
isExpanding = true
val toolsAnimator = ObjectAnimator.ofFloat(
binding.toolsLayout,
"translationY",
binding.toolsLayout.translationY,
0f
)
val closeAnimator = ObjectAnimator.ofFloat(
binding.close,
"translationX",
binding.close.translationX,
0f
)
val animatorSet = AnimatorSet()
animatorSet.duration = 300L
animatorSet.interpolator = AccelerateInterpolator()
animatorSet.playTogether(toolsAnimator, closeAnimator)
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationEnd(p0: Animator?) {
isExpanding = false
}
override fun onAnimationCancel(p0: Animator?) {
binding.toolsLayout.translationY = 0f
binding.close.translationX = 0f
isExpanding = false
}
override fun onAnimationStart(p0: Animator?) {}
override fun onAnimationRepeat(p0: Animator?) {}
})
animatorSet.start()
}
}
}
// ...
}
基本上就是判斷狀態以及從幾個View的目前位置歸0。
collapseToolsRunnable除了這兩個點外也要在move、resize等功能中做取消/註冊,避免功能衝突。
並且在onDestroy中取消Runnable。